"""
眨眼检测
使用mediapipe提供的解决方案
"""
import cv2
import mediapipe as mp
import math
from pygame import mixer
import time
import pyttsx3


class BlinkedDetect:
    def __init__(self):
        self.face_mesh = mp.solutions.face_mesh.FaceMesh()
        #左眼关键点序号
        self.FANCEMESH_LEFT_EYE = [362, 385, 387, 263, 373, 380]
        #右眼关键点序号
        self.FANCEMESH_RIGHT_EYE = [33, 160, 158, 133, 153, 144]
        #存储人脸关键点
        self.face_landmark = []
        self.frame = None
        self.index = 0
        self.is_blink = False

    def get_face_landmark(self, frame):
        """
        获取面部网格关键点
        :param frame:
        """
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        result = self.face_mesh.process(frame_rgb)
        multi_face_landmarks = result.multi_face_landmarks
        if multi_face_landmarks is None:
            return
        # 当前处理一张人脸图像
        face_landmarks = multi_face_landmarks[0]
        # 绘制关键点的序号
        landmark = face_landmarks.landmark
        # 将人脸关键点设置为成员变量
        self.face_landmark = landmark
        return face_landmarks

    def draw_style(self,frame,face_landmarks):
        # conns = mp.solutions.face_mesh_connections.FACEMESH_FACE_OVAL
        # point_style = mp.solutions.drawing_utils.DrawingSpec(color=(0, 100, 255), thickness=1)
        # line_style = mp.solutions.drawing_utils.DrawingSpec(color=(0, 100, 255), thickness=1)
        # # # 绘制样式
        # mp.solutions.drawing_utils.draw_landmarks(
        #     frame,
        #     face_landmarks,
        #     conns,
        #     point_style,
        #     line_style
        # )
        frame_h, frame_w, _ = frame.shape
        for index, lm in enumerate(self.face_landmark):
            if index not in self.FANCEMESH_LEFT_EYE and index not in self.FANCEMESH_RIGHT_EYE:
                continue
            x = round(frame_w * lm.x)
            y = round(frame_h * lm.y)
            cv2.putText(frame, str('.'),
                        org=(x - 2, y - 2),
                        fontFace=cv2.FONT_ITALIC,
                        fontScale=0.3,
                        color=(0, 255, 0),
                        thickness=2
                        )

    def get_Distance(self, p1, p2):
        return math.hypot(p1[0] - p2[0], p1[1] - p2[1])

    def cal_EAR(self):
        """
        计算纵横比
        :return:
        """
        p2 = self.index_convert_point(160)
        p6 = self.index_convert_point(144)

        p3 = self.index_convert_point(158)
        p5 = self.index_convert_point(153)

        p1 = self.index_convert_point(33)
        p4 = self.index_convert_point(133)

        #左眼各点位的距离
        dis_p2_6 = self.get_Distance(p2, p6)
        dis_p3_5 = self.get_Distance(p3, p5)
        dis_p1_4 = self.get_Distance(p1, p4)
        #计算纵横比
        EAR_left = (dis_p2_6+dis_p3_5) / (2 * dis_p1_4) * 10
        # print(EAR)
        # 右眼检测
        s1 = self.index_convert_point(362)
        s4 = self.index_convert_point(263)

        s2 = self.index_convert_point(385)
        s6 = self.index_convert_point(380)

        s3 = self.index_convert_point(387)
        s5 = self.index_convert_point(373)

        dis_s2_6 = self.get_Distance(s2, s6)
        dis_s3_5 = self.get_Distance(s3, s5)
        dis_s1_4 = self.get_Distance(s1, s4)

        EAR_right = (dis_s2_6 + dis_s3_5) / (2 * dis_s1_4) * 10
        # thresh = 2.2
        return EAR_right, EAR_left
        # index = self.index
        # start_time = self.time
        # print('开始时间'+str(index) + str(start_time))
        # if EAR_right < thresh and EAR_left < thresh :
        #     index = index+1
        #     end_time = time.time()
        #     print('结束时间'+str(end_time))
        #     self.index = index
        #     times = end_time - start_time
        #     print('时间差'+str(times))
        #     if times > 2 or index > 30 and not self.is_blink:
        #         self.time = time.time()
        #         # mixer.init()
        #         # mixer.music.load('warning.mp3')
        #         # mixer.music.play()
        #         self.say()
        #         print('----------------')
        #         print('您有点疲劳了！请注意休息'+str(index))
        #         print('----------------')
        #         self.is_blink = True
        #         self.write()

        # else:
        #     self.is_blink = False
        #     self.index = 0

    def write(self):
        s = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        f = open("users/behaviors.txt", 'a', encoding='utf-8')
        data = s + ' 您眨眼了，请注意休息!'
        f.write(data + '\n')
        f.close()   #关闭文件

    def detect(self, frame):
        self.frame = frame
        face_landmarks = self.get_face_landmark(frame)
        #如果没有检测到关键点直接返回
        if face_landmarks is None:
            return
        self.draw_style(frame, face_landmarks)
        #计算纵横比
        r, l = self.cal_EAR()
        self.time = time.time()
        self.warning(r, l)

    def index_convert_point(self, index):
        h, w, _ = self.frame.shape
        lm = self.face_landmark[index]
        x = round(lm.x * w)
        y = round(lm.y * h)
        return x, y

    #语音模块
    def say(self):
        mixer.init()
        mixer.music.load('warning.mp3')
        mixer.music.play()
        engine = pyttsx3.init()
        engine.setProperty('rate',200)
        engine.setProperty('volume',1)
        voices = engine.getProperty('voices')
        engine.setProperty('voices',voices[0].id)
        engine.say("您有点疲劳了！请注意休息!")
        engine.runAndWait()
        engine.stop()

    def warning(self, r, l):
        thresh = 2
        # print('开始时间' + str(index) + str(start_time))
        start_time = 0
        end_time = 0
        if r < thresh and l < thresh:
            self.index = self.index + 1
            # start_time = time.time()
            # print('结束时间' + str(end_time))
        # times = end_time - start_time
        # print('时间差' + str(times))
            if self.index > 45 and not self.is_blink:
            # if self.index > 10:
                # self.time = time.time()
                # mixer.init()
                # mixer.music.load('warning.mp3')
                # mixer.music.play()
                self.say()
                print('----------------')
                print('您有点疲劳了！请注意休息' + str(self.index))
                print('----------------')
                self.is_blink = True
                self.write()
        else:
            # end_time = time.time()
            self.is_blink = False
            self.index = 0